package com.ktwlsoft.archivemanage.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ktwlsoft.archivemanage.domain.business.businessService.SecurityRoleService;
import com.ktwlsoft.archivemanage.domain.business.businessService.VerificationCodeService;
import com.ktwlsoft.archivemanage.domain.business.repositoryService.AccountRepositoryService;
import com.ktwlsoft.archivemanage.domain.business.repositoryService.OperationRepositoryService;
import com.ktwlsoft.archivemanage.domain.dao.entity.Account;
import com.ktwlsoft.archivemanage.domain.dao.entity.ActionSource;
import com.ktwlsoft.archivemanage.domain.dao.entity.MenuSource;
import com.ktwlsoft.archivemanage.domain.dao.entity.OperationLog;
import com.ktwlsoft.archivemanage.payload.Result;
import com.ktwlsoft.archivemanage.payload.ResultType;
import com.ktwlsoft.archivemanage.payload.operationLog.SaveLogRequest;
import com.ktwlsoft.archivemanage.payload.security.*;
import com.ktwlsoft.archivemanage.service.security.JwtTokenProvider;
import com.ktwlsoft.archivemanage.service.security.UserPrincipal;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.List;

/**
 * 登录控制器
 *
 * @author LanJian
 */
@RestController
@RequestMapping("/auth")
@Api(value = "权限管理", description = "权限管理")
public class AuthController {


    private final AuthenticationManager authenticationManager;

    private final JwtTokenProvider jwtTokenProvider;

    private final SecurityRoleService securityRoleService;

    private final AccountRepositoryService accountRepositoryService;

    private final VerificationCodeService verificationCodeService;

    public AuthController(AuthenticationManager authenticationManager, JwtTokenProvider jwtTokenProvider, SecurityRoleService securityRoleService, AccountRepositoryService accountRepositoryService, VerificationCodeService verificationCodeService) {
        this.authenticationManager = authenticationManager;
        this.jwtTokenProvider = jwtTokenProvider;
        this.securityRoleService = securityRoleService;
        this.accountRepositoryService = accountRepositoryService;
        this.verificationCodeService = verificationCodeService;
    }

    @ApiOperation("登录，并且获取权限")
    @PostMapping("/login")
    public ResponseEntity<?> login(@Valid @RequestBody LoginRequest request) {
        if(!verificationCodeService.inspectVerification(request.getVerificationCode(),request.getVerificationId())){
            return ResponseEntity.status(401).body(Result.body(null, ResultType.CHECK_ERROR).withMessage("验证码不正确"));
        }
        if(!request.isPc()){
            if(!securityRoleService.existByUnitAccount(request.getUsernameOrPhone())){
                return ResponseEntity.status(401).body(Result.body(null, ResultType.CHECK_ERROR).withMessage("未找到相应企业账号！"));
            }
        }
        //区分是用户端还是客户端
        List<Account> accounts = accountRepositoryService.getByTeleNum(request.getUsernameOrPhone());
        if(accounts != null && !accounts.isEmpty()){
            for(Account account:accounts){
                if(request.getType().equals(LoginRequest.Type.ADMIN) && request.isPc() && !"立档单位".equals(account.getRoleName())){
                    request.setUsernameOrPhone(account.getUserName());
                    break;
                }
                if(!request.getType().equals(LoginRequest.Type.ADMIN) && !request.isPc() && "立档单位".equals(account.getRoleName())){
                    request.setUsernameOrPhone(account.getUserName());
                    break;
                }
            }
        }
        Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
                request.getUsernameOrPhone(),
                request.getPassword()
        ));
        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(authentication.getPrincipal()));
        if(request.getType().equals(LoginRequest.Type.ADMIN)) {
            if ("立档单位".equals(jsonObject.getString("roleName"))) {
                return ResponseEntity.status(401).body(Result.body(null, ResultType.CHECK_ERROR).withMessage("登录账号不正确"));
            }
        }
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = jwtTokenProvider.generateToken(authentication);
        if(!"立档单位".equals(jsonObject.getString("roleName"))) {
            OperationRepositoryService.saveLog(new SaveLogRequest(
                    OperationLog.OperationType.LOGGING,
                    "登录成功",
                    "",
                    OperationLog.BusinessType.LOGGING
            ));
        }
        if (request.isPc()) {
            AccountResponse account = securityRoleService.findAccount(request.getUsernameOrPhone());

            List<ActionSource> userActions = securityRoleService.findActionsByUserName(request.getUsernameOrPhone());
            List<MenuSource> userMenus = securityRoleService.findMenusByUserName(request.getUsernameOrPhone());
            return ResponseEntity.ok(Result.ok(new JwtAuthenticationResponse(jwt, userActions, userMenus, account)));
        } else {
            ArchiveUnitResponse archiveUnitResponse = securityRoleService.findArchiveUnitResponse(request.getUsernameOrPhone());
            return ResponseEntity.ok(Result.ok(new JwtAuthenticationMiniResponse(jwt, archiveUnitResponse)));
        }
    }

    @ApiOperation("退出")
    @PostMapping("signOut")
    public ResponseEntity<?> signOut(HttpServletRequest request, HttpServletResponse response){
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            Account user = UserPrincipal.getCurrentUser();
            if(user != null && !"立档单位".equals(user.getRoleName())) {
                OperationRepositoryService.saveLog(new SaveLogRequest(
                        OperationLog.OperationType.LOGGING_OUT,
                        "退出成功",
                        "",
                        OperationLog.BusinessType.LOGGING
                ));
            }
            //清除认证
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        return ResponseEntity.ok(Result.ok("操作成功"));
    }
}
